package org.wupuser.util;

import org.apache.tika.Tika;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

/**
 * 文件类型验证工具类 用于验证上传文件的各种属性，确保文件类型安全
 */
public class ValidateFileTypeUtil {
	/**
	 * 集中验证三种方法 综合验证文件后缀名、MIME类型和文件魔数
	 *
	 * @param file 文件对象
	 *
	 * @return 如果所有验证都通过则返回true，否则返回false
	 * @throws IOException 当读取文件流发生错误时抛出
	 */
	public static boolean validateFileType(MultipartFile file) throws IOException {
		if (file == null) {
			return false;  // 文件为空直接返回false
		}
		// 同时验证文件后缀、MIME类型和文件魔数
		return checkExtension(file) && checkMimeType(file) && checkFileHeader(file);
	}
	
	/**
	 * 验证文件后缀名 检查文件扩展名是否在允许的列表中
	 *
	 * @param file 文件对象
	 *
	 * @return 如果文件后缀名合法则返回true，否则返回false
	 */
	private static boolean checkExtension(MultipartFile file) {
		String fileName = file.getOriginalFilename();
		if (fileName == null) {
			return false;  // 文件名为空直接返回false
		}
		// 获取文件扩展名并转为小写
		String extension = fileName.substring(fileName.lastIndexOf("."))
			.toLowerCase();
		// 允许的文件扩展名列表
		List<String> allowedExtensions = List.of(
			".jpg",
			".jpeg",
			".png"
		);
		return allowedExtensions.contains(extension);
	}
	
	/**
	 * 验证文件MIME格式 检查文件的MIME类型是否在允许的列表中
	 *
	 * @param file 文件对象
	 *
	 * @return 如果MIME类型合法则返回true，否则返回false
	 */
	private static boolean checkMimeType(MultipartFile file) {
		String contentType = file.getContentType();
		// 允许的MIME类型列表
		List<String> allowedMimeTypes = List.of(
			"image/jpeg",
			"image/png",
			"image/jpg");
		return allowedMimeTypes.contains(contentType);
	}
	
	/**
	 * 验证文件魔数 通过读取文件内容来检测实际文件类型，防止伪造扩展名
	 *
	 * @param file 文件对象
	 *
	 * @return 如果文件实际类型合法则返回true，否则返回false
	 * @throws IOException 当读取文件流发生错误时抛出
	 */
	private static boolean checkFileHeader(MultipartFile file) throws IOException {
		Tika tika = new Tika();  // 创建Tika实例用于文件类型检测
		String detectedType = tika.detect(file.getInputStream()); // 检测文件类型
		List<String> allowedTypes = List.of(
			"image/jpeg",
			"image/png",
			"image/jpg");
		return allowedTypes.contains(detectedType);
	}
}
